package com.egg.mall.service.spu.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.egg.common.mybatis.service.impl.BaseServiceImpl;
import com.egg.common.util.JsonUtil;
import com.egg.mall.entity.spu.SpuAttribute;
import com.egg.mall.enums.AttributeTypeEnum;
import com.egg.mall.mapper.spu.SpuAttributeMapper;
import com.egg.mall.model.request.SpuPostOrPut;
import com.egg.mall.service.spu.ISpuAttributeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;


/**
 * @author east
 * @since 2022-08-08
 */
@Slf4j
@Service
public class SpuAttributeServiceImpl extends BaseServiceImpl<SpuAttributeMapper, SpuAttribute> implements ISpuAttributeService {


    /**
     * 保存属性
     *
     * @param spuId
     * @param list
     */
    @Transactional(rollbackFor = Throwable.class)
    @Override
    public void saveAttr(Serializable spuId, List<SpuPostOrPut.SpuAttribute> list) {
        List<Long> saveIds = list.stream()
                .filter(o -> ObjectUtil.isNotEmpty(o.getId()))
                .map(o -> Long.parseLong(o.getId())).collect(Collectors.toList());
        // 获取旧数据
        List<SpuAttribute> bySpuId = findAttrBySpuId(spuId);
        List<Long> existIds = bySpuId.stream().map(o -> o.getId()).collect(Collectors.toList());
        // 判断旧数据是否未被提交, 未被提交则视为需要删除
        List<Long> removeIds = existIds.stream()
                .filter(id -> !saveIds.contains(id))
                .collect(Collectors.toList());
        // 删除
        this.baseDel(removeIds);
        // 赋值
        List<SpuAttribute> spuAttributeList = list.stream().map(o -> {
            SpuAttribute spuAttribute = JsonUtil.objToObj(o, SpuAttribute.class);
            spuAttribute.setType(AttributeTypeEnum.ATTR.getCode());
            spuAttribute.setSpuId(Long.parseLong(spuId.toString()));
            return spuAttribute;
        }).collect(Collectors.toList());
        // 保存
        baseSave(spuAttributeList);
    }

    /**
     * 保存规格
     *
     * @param spuId
     * @param list
     */
    @Transactional(rollbackFor = Throwable.class)
    @Override
    public Map<String, Long> saveSpec(Serializable spuId, List<SpuPostOrPut.SpuAttribute> list) {
        List<Long> saveIds = list.stream()
                .filter(o -> !o.getId().startsWith(SPEC_TEMP_ID_PREFIX))
                .map(o -> Long.parseLong(o.getId())).collect(Collectors.toList());
        // 获取旧数据
        List<SpuAttribute> bySpuId = findSpecBySpuId(spuId);
        List<Long> existIds = bySpuId.stream().map(o -> o.getId()).collect(Collectors.toList());
        // 判断旧数据是否未被提交, 未被提交则视为需要删除
        List<Long> removeIds = existIds.stream()
                .filter(id -> !saveIds.contains(id))
                .collect(Collectors.toList());
        // 删除
        this.baseDel(removeIds);
        // 保存旧
        List<SpuAttribute> oldList = list.stream()
                .filter(o -> !o.getId().startsWith(SPEC_TEMP_ID_PREFIX))
                .map(o -> {
                    SpuAttribute spuAttribute = JsonUtil.objToObj(o, SpuAttribute.class);
                    spuAttribute.setType(AttributeTypeEnum.SPEC.getCode());
                    spuAttribute.setSpuId(Long.parseLong(spuId.toString()));
                    return spuAttribute;
                }).collect(Collectors.toList());
        baseSave(oldList);

        // 保存新
        Map<String, Long> tempWithNewSpecIdMap = new HashMap<>();
        List<SpuPostOrPut.SpuAttribute> newList = list.stream()
                .filter(o -> o.getId().startsWith(SPEC_TEMP_ID_PREFIX))
                .collect(Collectors.toList());
        newList.forEach(temp -> {
            String tempId = temp.getId();
            temp.setId(null);
            SpuAttribute spuAttribute = JsonUtil.objToObj(temp, SpuAttribute.class);
            spuAttribute.setType(AttributeTypeEnum.SPEC.getCode());
            spuAttribute.setSpuId(Long.parseLong(spuId.toString()));
            baseSave(spuAttribute);
            tempWithNewSpecIdMap.put(tempId, spuAttribute.getId());
        });
        return tempWithNewSpecIdMap;
    }

    @Override
    public List<SpuAttribute> findAttrBySpuId(Serializable spuId) {
        return findBySpuId(spuId, Optional.of(AttributeTypeEnum.ATTR));
    }

    @Override
    public List<SpuAttribute> findSpecBySpuId(Serializable spuId) {
        return findBySpuId(spuId, Optional.of(AttributeTypeEnum.SPEC));
    }

    @Override
    public List<SpuAttribute> findBySpuId(Serializable spuId) {
        return findBySpuId(spuId, Optional.empty());
    }

    @Override
    public List<SpuAttribute> findBySpuId(Serializable spuId, Optional<AttributeTypeEnum> type) {
        if (ObjectUtil.isEmpty(spuId)) {
            return Collections.emptyList();
        }
        return findBySpuId(Collections.singletonList(spuId), type);
    }

    @Override
    public List<SpuAttribute> findBySpuId(Collection<? extends Serializable> spuId, Optional<AttributeTypeEnum> type) {
        if (ObjectUtil.isEmpty(spuId)) {
            return Collections.emptyList();
        }
        LambdaQueryWrapper<SpuAttribute> qw = buildLambdaQw();
        qw.in(SpuAttribute::getSpuId, spuId);
        type.ifPresent(o -> qw.eq(SpuAttribute::getType, o.getCode()));
        return list(qw);
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public void delBySpuId(Collection<? extends Serializable> spuId) {
        if (ObjectUtil.isEmpty(spuId)) {
            return;
        }
        LambdaQueryWrapper<SpuAttribute> qw = buildLambdaQw();
        qw.in(SpuAttribute::getSpuId, spuId);
        remove(qw);
    }


}
